/*******************************************************************************
* Copyright (c) 2007, 2008 Gregory Jordan
*
* This file is part of PhyloWidget.
*
* PhyloWidget is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 2 of the License, or (at your option) any later
* version.
*
* PhyloWidget is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* PhyloWidget. If not, see <http://www.gnu.org/licenses/>.
*/
package org.phylowidget.render;
import java.awt.FileDialog;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import org.andrewberman.ui.UIUtils;
import org.phylowidget.PWContext;
import org.phylowidget.PWPlatform;
import org.phylowidget.PhyloTree;
import org.phylowidget.TreeManager;
import org.phylowidget.tree.PhyloNode;
import org.phylowidget.tree.RootedTree;
import processing.core.PApplet;
import processing.core.PConstants;
import processing.core.PGraphics;
import processing.core.PGraphicsJava2D;
import com.lowagie.text.Document;
public class RenderOutput
{
public static boolean isOutputting = false;
public static Document doc;
public static synchronized void savePDF(PApplet p, BasicTreeRenderer r, boolean zoomToFull, boolean showAllLabels)
{
PWContext context = PWPlatform.getInstance().getThisAppContext();
isOutputting = true;
RootedTree t = r.getTree();
float oldThreshold = context.config().renderThreshold;
context.config().renderThreshold = Integer.MAX_VALUE;
boolean oldDoubleBuff = context.config().useDoubleBuffering;
context.config().useDoubleBuffering = false;
float oldTextSize = context.config().minTextSize;
if (showAllLabels)
context.config().minTextSize = 0;
try
{
context.getPW().setMessage("Outputting PDF...");
preprocess(t);
// File f = p.outputFile("Save PDF as...");
// String s = p.selectOutput("Save PDF as...");
String fileType = "PDF";
FileDialog fd =
new FileDialog(context.ui().getFrame(), "Choose your desination " + fileType + " file.",
FileDialog.SAVE);
fd.pack();
fd.setVisible(true);
String directory = fd.getDirectory();
String filename = fd.getFile();
if (filename == null)
{
context.getPW().setMessage("Output cancelled.");
return;
}
// Fix a non-PDF extension.
if (!filename.toLowerCase().endsWith((".pdf")))
{
filename += ".pdf";
}
File f = new File(directory,filename);
p.noLoop();
PGraphics canvas = p.createGraphics(p.width, p.height, PConstants.PDF);
canvas.setPath(f.getAbsolutePath());
canvas.setSize(p.width, p.height);
canvas.beginDraw();
if (context.config().debug)
System.out.println("BEGIN DRAW");
/*
* Create the render rectangle.
*/
Rectangle2D.Float rect = TreeManager.cameraRect;
Rectangle2D.Float oldRect = rect;
if (zoomToFull)
{
TreeManager.camera.fillScreen(0.5f);
TreeManager.camera.fforward();
context.trees().update();
rect = TreeManager.cameraRect;
}
/*
* Do the rendering!
*/
r.render(canvas, rect.x, rect.y, rect.width, rect.height, true);
if (context.config().debug)
System.out.println("END DRAW");
canvas.endDraw();
canvas.dispose();
context.getPW().setMessage("Output complete.");
} catch (Exception e)
{
e.printStackTrace();
context.getPW().setMessage("PDF output failed: " + e.getMessage());
} finally
{
context.config().renderThreshold = oldThreshold;
context.config().minTextSize = oldTextSize;
context.config().useDoubleBuffering = oldDoubleBuff;
isOutputting = false;
p.loop();
}
}
public static synchronized void save(PApplet p, BasicTreeRenderer r, boolean zoomToFull, boolean showAllLabels,
String fileType, int w, int h)
{
PWContext context = PWPlatform.getInstance().getThisAppContext();
isOutputting = true;
float oldThreshold = context.config().renderThreshold;
context.config().renderThreshold = Integer.MAX_VALUE;
boolean oldDoubleBuff = context.config().useDoubleBuffering;
context.config().useDoubleBuffering = false;
float oldTextSize = context.config().minTextSize;
if (showAllLabels)
context.config().minTextSize = 0;
try
{
context.getPW().setMessage("Outputting image...");
RootedTree t = r.getTree();
preprocess(t);
FileDialog fd =
new FileDialog(context.ui().getFrame(), "Choose your desination " + fileType + " file.",
FileDialog.SAVE);
fd.pack();
fd.setVisible(true);
String directory = fd.getDirectory();
String filename = fd.getFile();
if (filename == null)
{
context.getPW().setMessage("Output cancelled.");
return;
}
if (!filename.toLowerCase().endsWith(fileType.toLowerCase()))
{
filename += "." + fileType.toLowerCase();
}
File f = new File(directory, filename);
p.noLoop();
PGraphicsJava2D canvas = (PGraphicsJava2D) p.g;
Image oldImage = canvas.image;
Graphics2D oldG2 = canvas.g2;
int oldW = canvas.width;
int oldH = canvas.height;
canvas.width = w;
canvas.height = h;
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
UIUtils.setRenderingHints(g2);
canvas.image = img;
canvas.g2 = g2;
canvas.beginDraw();
prettyHints(canvas);
canvas.background(255);
/*
* Create the render rectangle.
*/
Rectangle2D.Float rect = TreeManager.cameraRect;
float wFactor = w / oldW;
float hFactor = h / oldH;
if (zoomToFull)
rect.setRect(0, 0, oldW, oldH);
// System.out.println(rect);
r.render(canvas, rect.x * wFactor, rect.y * hFactor, rect.width * wFactor, rect.height * hFactor, true);
canvas.endDraw();
canvas.loadPixels();
canvas.save(f.getAbsolutePath());
g2.dispose();
canvas.image = oldImage;
canvas.g2 = oldG2;
canvas.width = oldW;
canvas.height = oldH;
context.getPW().setMessage("Output complete.");
} catch (Exception e)
{
e.printStackTrace();
context.getPW().setMessage("Output failed: " + e.getMessage());
System.gc();
return;
} finally
{
context.config().renderThreshold = oldThreshold;
context.config().minTextSize = oldTextSize;
context.config().useDoubleBuffering = oldDoubleBuff;
isOutputting = false;
p.loop();
}
}
private static void prettyHints(PGraphicsJava2D g)
{
Graphics2D g2 = g.g2;
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
}
private static void preprocess(RootedTree t)
{
/*
* Go through all the nodes and remove any cut/copy/paste states.
*/
ArrayList nodes = new ArrayList();
t.getAll(t.getRoot(), null, nodes);
for (int i = 0; i < nodes.size(); i++)
{
PhyloNode n = (PhyloNode) nodes.get(i);
n.setState(PhyloNode.NONE);
}
PWContext context = PWPlatform.getInstance().getThisAppContext();
PhyloTree pt = (PhyloTree) context.trees().getTree();
pt.hoveredNode = null;
}
}